/*
 * Copyright (C) 2018 Nils Petzaell
 *
 * This file is part of SchemaSpy.
 *
 * SchemaSpy is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * SchemaSpy is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with SchemaSpy.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
package org.schemaspy.testing;

import org.assertj.core.api.SoftAssertions;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.assertj.core.api.Assertions.assertThat;

public class HtmlOutputValidator {

    private HtmlOutputValidator() {};

    private static Comparator<String> htmlComparator = (a, e) -> {
        String trimmed = e.trim();
        if (trimmed.startsWith("<strong>Generated by")) {
            return 0;
        } else if (trimmed.startsWith("<area shape=")) {
            return 0;
        } else if (trimmed.startsWith("<p>Generated on")) {
            return 0;
        } else if (trimmed.startsWith("<p>Database Type")) {
            return 0;
        } else if (trimmed.startsWith("// dot")) {
            return 0;
        } else if (trimmed.startsWith("// SchemaSpy rev")) {
            return 0;
        }
        return a.compareTo(e);
    };

    public static SoftAssertions hasProducedValidOutput(Path actualPath, Path expectedPath) throws IOException {
        List<Path> actualPaths;
        try (Stream<Path> pathStream = Files.find(actualPath, 5, (p, a) -> a.isRegularFile())) {
            actualPaths = pathStream.filter(p -> {
                String path = p.toString().toLowerCase();
                return path.endsWith("html");
            }).collect(Collectors.toList());
        }
        assertThat(actualPaths.size()).isGreaterThan(0);
        SoftAssertions softAssertions = new SilentSoftAssertions();
        for (Path actual : actualPaths) {
            Path expected = Paths.get(expectedPath.toString(), actualPath.relativize(actual).toString());
            if (expected.toFile().exists()) {
                List<String> actualLines = Files.readAllLines(actual, StandardCharsets.UTF_8);
                List<String> expectedLines = Files.readAllLines(expected, StandardCharsets.UTF_8);
                softAssertions.assertThat(actualLines).as("%s doesn't have the expected number of lines: %s", actual.toString(), expectedLines.size()).hasSameSizeAs(expectedLines);
                softAssertions.assertThat(actualLines).usingElementComparator(htmlComparator).as("%s isn't as expected", actual.toString()).containsAll(expectedLines);
            } else {
                softAssertions.fail("Missing expectation for %s", actualPath.relativize(actual).toString());
            }
        }
        return softAssertions;
    }

    public static SoftAssertions hasSameContent(Path actualFile, Path expectedFile) throws IOException {
        SoftAssertions softAssertions = new SilentSoftAssertions();
        List<String> actualLines = Files.readAllLines(actualFile, StandardCharsets.UTF_8);
        List<String> expectedLines = Files.readAllLines(expectedFile, StandardCharsets.UTF_8);
        softAssertions.assertThat(actualLines).as("%s doesn't have the expected number of lines: %s", actualFile.toString(), expectedLines.size()).hasSameSizeAs(expectedLines);
        softAssertions.assertThat(actualLines).usingElementComparator(htmlComparator).as("%s isn't as expected", actualFile.toString()).containsAll(expectedLines);
        return softAssertions;
    }
}
